<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\Install\Command;

use Hyperf\Command\Annotation\Command;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Contract\ConfigInterface;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use MoChat\App\Install\Logic\Upgrade1D3D0Logic;
use MoChat\App\Install\Logic\Upgrade1D3D1Logic;
use MoChat\App\Install\Logic\Upgrade1D4D0Logic;
use MoChat\App\Install\Logic\Upgrade1D5D0Logic;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Question\Question;

/**
 * @Command
 */
class UpgradeCommand extends HyperfCommand
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @Inject
     * @var ConfigInterface
     */
    protected $config;

    /**
     * @var string sql安装文件
     */
    protected $sqlFile;

    protected $upgradeLogics = [
        '1.3.0' => Upgrade1D3D0Logic::class,
        '1.3.1' => Upgrade1D3D1Logic::class,
        '1.4.0' => Upgrade1D4D0Logic::class,
        '1.5.0' => Upgrade1D5D0Logic::class,
    ];

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;

        parent::__construct('mochat:upgrade');
    }

    public function configure()
    {
        parent::configure();
        $this->setDescription('MoChat 系统升级脚本');
        $this->addArgument('version', InputArgument::REQUIRED, '准备升级的版本');
    }

    public function handle(): void
    {
        try {
            $version = trim($this->input->getArgument('version'));
            $this->mysqlDataImport($version);

            if (isset($this->upgradeLogics[$version])
                && ! empty($this->upgradeLogics[$version])
                && class_exists($this->upgradeLogics[$version])
            ) {
                $upgradeLogic = make($this->upgradeLogics[$version]);
                $upgradeLogic($this);
            }

            $this->line('MoChat 系统升级成功', 'info');
        } catch (\Exception $e) {
            $this->error('MoChat 系统升级失败，错误：' . $e->getMessage());
            $this->error($e->getTraceAsString());
        }
    }

    /**
     * Prompt the user for input with validator.
     *
     * @param null|mixed $default
     * @return mixed
     */
    public function askWithValidator(string $question, callable $validator, $default = null)
    {
        $question = new Question($question, $default);
        $question->setValidator($validator);
        return $this->output->askQuestion($question);
    }

    private function mysqlDataImport(string $version): void
    {
        $dbVersion = Db::select('select VERSION() AS version;');
        $dbVersion = empty($dbVersion[0]->version) ? 5.6 : (float) $dbVersion[0]->version;
        if ($dbVersion < 5.7) {
            throw new \RuntimeException('mysql版本号错误，需要版本号 >= 5.7');
        }

        $this->sqlFile = BASE_PATH . '/storage/install/upgrade_' . $version . '.sql';
        if (! file_exists($this->sqlFile)) {
            $this->alert(sprintf('%s版本无SQL需要导入', $version));
            return;
        }

        $sqlArr = explode(';', file_get_contents($this->sqlFile));
        foreach ($sqlArr as $item) {
            $item = trim($item);
            if (empty($item)) {
                continue;
            }
            Db::statement((string) Db::raw($item . ';'));
        }
    }
}
